using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

public sealed class ObjectFactory<IDtype, BaseClassName>
{
    // Function pointer declaration   
    private delegate BaseClassName ObjectCreator();

    // Database of function pointes to create objects
    private Dictionary<IDtype, ObjectCreator> m_ObjectCreators;

    #region Instance
    private static ObjectFactory<IDtype, BaseClassName> m_instance;
    public static ObjectFactory<IDtype, BaseClassName> Instance
    {
        get
        {
            if( m_instance != null)
            return m_instance;
           
            m_instance  = new ObjectFactory<IDtype, BaseClassName>();
            return m_instance;
        }

    }
    private ObjectFactory()
    {
      
    }
    #endregion

    public void Initalize()
    {
        m_ObjectCreators = new Dictionary<IDtype, ObjectCreator>();
    }
    //Private function to create an object
    private static BaseClassName ConstructObject<DerivedClassType>() where DerivedClassType : BaseClassName, new()
    {
        return new DerivedClassType();
    }

    public bool RegisterClassType<DerivedClassType>(IDtype id) where DerivedClassType : BaseClassName, new()
    {
        ObjectCreator objectFunctor = ConstructObject<DerivedClassType>;
        m_ObjectCreators.Add(id, objectFunctor);


        return true;
    }

    public bool UnRegisterClassType(IDtype id)
    {
        if (m_ObjectCreators.ContainsKey(id))
        {
            m_ObjectCreators.Remove(id);
            return true;
        }
        else
            return false;
    }

    public BaseClassName CreateObject(IDtype id)
    {
        try
        {
            ObjectCreator createFunctor = m_ObjectCreators[id];
            return createFunctor();
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
            return default(BaseClassName);
        }
    }

    public void ShutdownObjectFactory()
    {
        m_ObjectCreators.Clear();
    }
}